﻿using System;
using System.Collections.Generic;
using System.Text;

namespace XMK.Utils
{
    /// <summary>
    /// 通用类型转换，提供类型转换处理方法
    /// </summary>
    public sealed class ParseHelper
    {
        #region 注释方法
        /*
        public static readonly int DEFAULT_INT = 0;
        public static readonly string DEFAULT_STRING = string.Empty;
        public static readonly double DEFAULT_DOUBLE = 0.0;
        public static readonly decimal DEFAULT_DECIMAL = decimal.Zero;
        public static readonly DateTime DEFAULT_DATETIME = new DateTime(1900,1,1);
        /// <summary>
        /// 时间格式：yyyy-MM-dd hh:mm:ss:fff
        /// </summary>
        public static readonly string YYYYMMDDHHMMSSFFF = "yyyy-MM-dd hh:mm:ss:fff";
        /// <summary>
        /// 时间格式：yyyy-MM-dd
        /// </summary>
        public static readonly string YYYY_MM_DD = "yyyy-MM-dd";
        /// <summary>
        /// 时间格式：yyyyMMdd
        /// </summary>
        public static readonly string YYYYMMDD = "yyyyMMdd";


        #region 常量

        //转换出错信息
        private const string CAST_ERROR_MSG = "ParserHelper.{0} Error.object:{1},type:{2}.";
        //不能为空
        private const string NULL_ERROR_MSG = "ParserHelper.{0} Error.Object is null or dbnull.";

        #endregion

        #region 新公共静态方法
        public static bool IsNull(object obj)
        {
            return obj == null || obj == DBNull.Value;
        }
        public static bool IsEmpty(object obj)
        {
            return IsNull(obj) || obj.ToString().Length == 0;
        }
        #region toInt
        /// <summary>
        /// 把对象转换为Int
        /// </summary>
        /// <param name="obj">需要转换的对象</param>
        /// <param name="defaultVal">默认值</param>
        /// <returns>Int</returns>
        public static int ParseInt(object obj, int defaultVal)
        {
            string s = ParseString(obj);
            if (s.Length == 0)
                return defaultVal;
            int i = defaultVal;
            int.TryParse(s, out i);
            return i;
        }
        public static int ParseInt(object obj)
        {
            return ParseInt(obj, DEFAULT_INT);
        }
        #endregion
        #region toString
        /// <summary>
        /// 把对象转换为String
        /// </summary>
        /// <param name="obj">需要转换的对象</param>
        /// <param name="defaultVal">默认值</param>
        /// <returns>String</returns>
        public static string ParseString(object obj, string defaultVal)
        {
            if (IsNull(obj))
                return defaultVal;
            return obj.ToString();
        }
        public static string ParseString(object obj)
        {
            return ParseString(obj, DEFAULT_STRING);
        }
        #endregion
        #region toDouble
        /// <summary>
        /// 把对象转换为Double
        /// </summary>
        /// <param name="obj">需要转换的对象</param>
        /// <param name="defaultVal">默认值</param>
        /// <returns>Double</returns>
        public static double ParseDouble(object obj, double defaultVal)
        {
            if (IsEmpty(obj))
                return defaultVal;
            double d = defaultVal;
            double.TryParse(obj.ToString(),out d);
            return d;
        }
        public static double ParseDouble(object obj)
        {
            return ParseDouble(obj, DEFAULT_DOUBLE);
        }
        #endregion
        #region toDecimal
        public static decimal ParseDecimal(object obj, decimal defaultVal)
        {
            if (IsEmpty(obj))
                return defaultVal;
            decimal d = defaultVal;
            decimal.TryParse(obj.ToString(), out d);
            return d;
        }
        public static decimal ParseDecimal(object obj)
        {
            return ParseDecimal(obj, DEFAULT_DECIMAL);
        }
        #endregion
        #region toDateTime
        public static DateTime ParseDateTime(object obj, DateTime defaultVal)
        {
            if (IsEmpty(obj))
                return defaultVal;
            DateTime d = defaultVal;
            DateTime.TryParse(obj.ToString(), out d);
            return d;
        }
        public static DateTime ParseDateTime(object obj)
        {
            return ParseDateTime(obj, DEFAULT_DATETIME);
        }
        #endregion


        public static string DateTimeToString(DateTime obj, string format)
        {
            return obj.ToString(format);
        }
        public static string DateTimeToString(DateTime obj)
        {
            return DateTimeToString(obj, YYYY_MM_DD);
        }

        /// <summary>
        /// 日期转成年月日int型
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int DateTimeToYMDString(DateTime obj)
        {
            return ParseInt(DateTimeToString(obj, YYYYMMDD));
        }
        /// <summary>
        /// 日期转成年月日int型
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int DateTimeToYMDString(object obj)
        {
            return ParseInt(DateTimeToString(ParseDateTime(obj), YYYYMMDD));
        }
         * */
        #endregion
        #region 公共静态方法
        /// <summary>
        /// 对Object进行指定类型的转换,当对象为空或转换错误时返回指定默认值
        /// 注意：当Obj为字符类型但内容包含小数且T为整型时，转换错误。如："20.22" 转换为Int错误;而20.22转换为Int=20
        /// 当Obj为数字且以科学计数法表示时转换为String会变为科学计数法，且精度丢失，所以建议用Decimal
        /// </summary>
        /// <typeparam name="T">支持类型：double,int,long,ushort,decimal,float,short,string,datetime</typeparam>
        /// <param name="obj">需要转换的对象</param>
        /// <param name="defaultVal">默认值</param>
        /// <returns>T型的数据</returns>
        public static T Parse<T>(object obj, T defaultVal)
        {
            if (obj != null && obj != DBNull.Value && !string.IsNullOrEmpty(obj.ToString()))
            {
                Type type = typeof(T);
                try
                {
                    return (T)Convert.ChangeType(obj, type);
                }
                catch// (Exception ex)
                {
                   //LogHelper.WriteExceptionLog("Wind.Utils.ParseHelper.Parse<T>(" + obj.ToString() + ")", ex);
                }
            }
            return defaultVal;
        }
        /// <summary>
        /// 对Object进行指定类型的转换,当对象为空或转换错误时返回默认值
        /// 注意：当Obj为字符类型但内容包含小数且T为整型时，转换错误。如："20.22" 转换为Int错误;而20.22转换为Int=20
        /// 当Obj为数字且以科学计数法表示时转换为String会变为科学计数法，且精度丢失，所以建议用Decimal
        /// </summary>
        /// <typeparam name="T">支持类型：double,int,long,ushort,decimal,float,short,string,datetime</typeparam>
        /// <param name="obj">需要转换的对象</param>
        /// <returns>T型的数据</returns>
        public static T Parse<T>(object obj)
        {
            return Parse<T>(obj, GetDefaultVal<T>());
        }
        /// <summary>
        /// 对object进行指定类型的转换
        /// </summary>
        /// <param name="obj">需要转换的对象</param>
        /// <param name="covertToType">转换的类型</param>
        /// <returns>object</returns>
        public static object Parse(object obj, Type covertToType)
        {
            if (obj != null && obj != DBNull.Value && !string.IsNullOrEmpty(obj.ToString()))
            {
                try
                {
                    return Convert.ChangeType(obj, covertToType);
                }
                catch// (Exception ex)
                {
                    //LogHelper.WriteExceptionLog("Wind.Utils.ParseHelper.Parse(" + obj.ToString() + ")", ex);
                }
            }
            return null;
        }
        /// <summary>
        /// 对Object进行指定类型的转换,并判断转换结果是否为空，当对象为空或转换错误或与指定的NullVal相等时,返回true,Val为类型默认值
        /// </summary>
        /// <typeparam name="T">支持类型：double,int,long,ushort,decimal,float,short,string,datetime</typeparam>
        /// <param name="obj">需要转换的对象</param>
        /// <param name="nullVal">空值标示</param>
        /// <param name="outValue">输出值</param>
        /// <returns>对象是否为空，true为空，false为非空</returns>
        public static bool ParseIsNull<T>(object obj, T nullVal, ref T outValue)
        {
            if (obj != null && obj != DBNull.Value && !string.IsNullOrEmpty(obj.ToString()))
            {
                try
                {
                    outValue = (T)Convert.ChangeType(obj, typeof(T));
                    if (!outValue.Equals(nullVal))
                        return false;
                }
                catch// (Exception ex)
                {
                    //LogHelper.WriteExceptionLog("Wind.Utils.ParseHelper.ParseIsNull<T>(" + obj.ToString() + ")", ex);
                }
            }
            return true;
        }
        /// <summary>
        /// 枚举数据类型转换,可设置是否区分大小写,当对象为空或转换错误时返回指定默认值
        /// </summary>
        /// <typeparam name="T">支持枚举类型</typeparam>
        /// <param name="obj">要转换的对象</param>
        /// <param name="ignoreCase">忽略大小写</param>
        /// <param name="defaultVal">默认值</param>
        /// <returns>T型值</returns>
        public static T ParseEnum<T>(object obj, bool ignoreCase, T defaultVal)
        {
            T val = defaultVal;
            if (obj != null && obj != DBNull.Value && !string.IsNullOrEmpty(obj.ToString()))
            {
                try
                {
                    ParseEnum<T>(obj, ignoreCase, ref val);
                }
                catch// (Exception ex)
                {
                    //LogHelper.WriteExceptionLog("Wind.Utils.ParseHelper.ParseEnum<T>", ex);
                }
            }
            return val;
        }
        /// <summary>
        /// 枚举数据类型转换,不区分大小写,当对象为空或转换错误时返回指定默认值
        /// </summary>
        /// <typeparam name="T">支持枚举类型</typeparam>
        /// <param name="obj">要转化的对象</param>
        /// <param name="defaultVal">默认值</param>
        /// <returns>T型数据</returns>
        public static T ParseEnum<T>(object obj, T defaultVal)
        {
            return ParseEnum<T>(obj, true, defaultVal);
        }
        /// <summary>
        /// 浮点形保留小数点
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static decimal? ToDecimal(decimal? d)
        {
            if (d.HasValue)
            {
                if (d.Value.ToString().IndexOf(".") < 0)
                {
                    return decimal.Parse(d.Value.ToString("f1"));
                }
                return d.Value;
            }

            return null;
            
        }
        #region 时间转换方法
        /// <summary>
        /// 日期转换为字符串，格式为yyyy-MM-dd hh:mm:ss
        /// </summary>
        /// <param name="date">日期参数</param>
        /// <returns>yyyy-MM-dd hh:mm:ss格式的日期字符串</returns>
        public static string ParseDateTimeToStr(DateTime date)
        {
            return ParseDateTimeToStr(date, "yyyy-MM-dd hh:mm:ss");
        }
        
        /// <summary>
        /// 日期换化为字符串
        /// </summary>
        /// <param name="date">要转化的日期</param>
        /// <param name="format">日期格式:d,D,F,f,G,g,M,m,o,R,r,s,T,t,U,u,y,Y或yyyy,MM,dd,hh,mm,ss</param>
        /// <returns>特定日期格式的日期字符串</returns>
        public static string ParseDateTimeToStr(DateTime date, string format)
        {
            return date.ToString(format);
        }
        /// <summary>
        /// 时间字符串转换为其他时间格式字符串
        /// </summary>
        /// <param name="dateStr">时间字符串（格式为yyyy-MM-dd）</param>
        /// <param name="format">转换后的字符串格式</param>
        /// <returns>按照format指定的格式字符串</returns>
        public static string ParseDateTimeToStr(string dateStr, string format)
        {
            return ParseDateTimeToStr(dateStr, "yyyy-MM-dd", format);
        }
        /// <summary>
        /// 指定格式的时间字符串转换为其他格式字符串
        /// </summary>
        /// <param name="dateStr">时间字符串（输入为null或空则返回null）</param>
        /// <param name="dateFormat">时间字符串的格式</param>
        /// <param name="format">转换后的字符串格式</param>
        /// <returns>按照format指定的格式字符串</returns>
        public static string ParseDateTimeToStr(string dateStr, string dateFormat, string format)
        {
            if (String.IsNullOrEmpty(dateStr))
                return null;
            DateTime date = ParseStrToDateTime(dateStr.Trim(), dateFormat);
            return date.ToString(format);
        }
        /// <summary>
        /// 字符串转化日期类型
        /// </summary>
        /// <param name="dateStr">要转化的值（支持格式为2011/11/11 22:22和2011-11-11 22:22:22）</param>
        /// <returns>日期类型的值</returns>
        public static DateTime ParseStrToDateTime(string dateStr)
        {
            DateTime result = new DateTime();
            dateStr = dateStr.Trim();
            if (!string.IsNullOrEmpty(dateStr))
            {
                result = DateTime.Parse(dateStr);
            }
            return result;
        }
        /// <summary>
        /// 对象转换为日期类型
        /// </summary>
        /// <param name="dateObj">需转换对象</param>
        /// <returns>日期类型的值</returns>
        public static DateTime ParseStrToDateTime(Object dateObj)
        {
            if (IsNull(dateObj))
                return GetDefaultVal<DateTime>();
            return ParseStrToDateTime(dateObj.ToString());
        }
        /// <summary>
        /// 将特定格式的字符串转换成日期型数据
        /// </summary>
        /// <param name="dateStr">要转化的值</param>
        /// <param name="format">日期格式</param>
        /// <returns>用特定格式的字符串转换成的日期型数据</returns>
        public static DateTime ParseStrToDateTime(string dateStr, string format)
        {
            DateTime result = new DateTime();
            dateStr = dateStr.Trim();
            if (!string.IsNullOrEmpty(dateStr))
            {
                result = DateTime.ParseExact(dateStr, format, null);
            }
            return result;
        }
        /// <summary>
        /// 字符串转化日期类型（不抛出异常）
        /// </summary>
        /// <param name="dateStr">需转换的字符串</param>
        /// <param name="date">转换后的日期</param>
        /// <returns>是否转换成功</returns>
        public static bool TryParseStrToDateTime(string dateStr, out DateTime date)
        {
            if (String.IsNullOrEmpty(dateStr) || !DateTime.TryParse(dateStr, out date))
            {
                date = new DateTime();
                return false;
            }
            return true;
        }
        /// <summary>
        /// 字符串按照指定格式转化日期类型（不抛出异常）
        /// </summary>
        /// <param name="dateStr">需转换的字符串</param>
        /// <param name="dateFormat">字符串的日期格式</param>
        /// <param name="date">转换后的日期</param>
        /// <returns>是否转换成功</returns>
        public static bool TryParseStrToDateTime(string dateStr, string dateFormat, out DateTime date)
        {
            if (String.IsNullOrEmpty(dateStr) || !DateTime.TryParseExact(dateStr, dateFormat, null, System.Globalization.DateTimeStyles.None, out date))
            {
                date = new DateTime();
                return false;
            }
            return true;
        }


        /// <summary>
        /// 适应于从数据库中取得时间字段转换为文本格式
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static string ToDataStr(object o)
        {
            if (o == null || o == DBNull.Value)
                return string.Empty;
            DateTime dt = ParseStrToDateTime(o.ToString());
            return ParseDateTimeToStr(dt, "yyyy-MM-dd").Replace("1900-01-01","");
        }
        #endregion
        #endregion
        #region 私有静态方法
        /// <summary>
        /// 获取基础类型的默认值
        /// </summary>        
        /// <returns>T型数据的默认值</returns>
        private static T GetDefaultVal<T>()
        {
            Type type = typeof(T);
            if (IsNumType(type))
                return Parse<T>(0, type);
            if (IsStringType(type))
                return Parse<T>(string.Empty, type);
            if (IsDateTimeType(type))
                return Parse<T>(new DateTime(1000, 1, 1), type);
            if (IsBoolType(type))
                return Parse<T>(false, type);

            throw new InvalidCastException(String.Format("类型({0})不是c#基础类型！", type.Name));
        }

        /// <summary>
        /// 测试是否为数值类型
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns>是否为数值类型的值，true为是，false为不是</returns>
        private static bool IsNumType(Type type)
        {
            return type.Equals(typeof(double)) || type.Equals(typeof(int)) || type.Equals(typeof(long)) ||
                type.Equals(typeof(uint)) || type.Equals(typeof(ushort)) || type.Equals(typeof(ulong)) ||
                type.Equals(typeof(decimal)) || type.Equals(typeof(float)) || type.Equals(typeof(short));
        }

        /// <summary>
        /// 测试是否是string类型
        /// </summary>
        /// <param name="type">传入的type</param>
        /// <returns>true标示为string类型，否则不是</returns>
        private static bool IsStringType(Type type)
        {
            return type.Equals(typeof(string));
        }

        /// <summary>
        /// 测试是否是DateTime类型
        /// </summary>
        /// <param name="type">传入的type</param>
        /// <returns>true标示为datetime类型，否则不是</returns>
        private static bool IsDateTimeType(Type type)
        {
            return type.Equals(typeof(DateTime));
        }

        /// <summary>
        /// 测试是否是Bool类型
        /// </summary>
        /// <param name="type">传入的type</param>
        /// <returns>true标示为bool类型，否则不是</returns>
        private static bool IsBoolType(Type type)
        {
            return type.Equals(typeof(bool));
        }

        /// <summary>
        /// 判断一个对象是不是为空值
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>true为空，false为非空对象</returns>
        public static bool IsNull(object obj)
        {
            return IsNull(obj, false);
        }

        /// <summary>
        /// 判断一个对象是不是为空值，并根据参数决定为空时是否抛异常
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="isNullThrowException">为空时是否抛出异常</param>
        /// <returns>true为空，false为非空对象</returns>
        public static bool IsNull(object obj, bool isNullThrowException)
        {
            bool flag = false;

            if (obj == null)
            {
                flag = true;
                if (isNullThrowException)
                {
                    throw new Exception("参数为空！");
                }
                return flag;
            }

            if (Convert.IsDBNull(obj))
            {
                flag = true;
                if (isNullThrowException)
                {
                    throw new Exception("参数为空！");
                }
            }
            return flag;
        }

        /// <summary>
        /// 类型转换
        /// </summary>
        /// <typeparam name="T">要转换的类型</typeparam>
        /// <param name="obj">要转换的对象</param>
        /// <param name="type">类型</param>
        /// <returns>T型数据</returns>
        private static T Parse<T>(object obj, Type type)
        {
            return (T)Convert.ChangeType(obj, type);
        }

        /// <summary>
        /// 枚举类型转换
        /// </summary>
        /// <typeparam name="T">要转换的枚举类型</typeparam>
        /// <param name="obj">要转换的枚举对象</param>
        /// <param name="ignoreCase">忽略大小写</param>
        /// <param name="val">输出值</param>
        /// <returns>true为转换成功，否则不成功</returns>
        private static bool ParseEnum<T>(object obj, bool ignoreCase, ref T val)
        {
            bool result = false;
            Type type = typeof(T);
            object tempVal = Enum.Parse(type, obj.ToString(), ignoreCase);
            if (Enum.IsDefined(type, tempVal))
            {
                val = (T)tempVal;
                result = true;
            }
            return result;
        }

        #endregion
    }
}
